﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;

namespace CNStreaming
{
    /// <summary>
    /// Manages a stream that can be used to hold serialized objects. These can be used
    /// for example to send messages or to store in a DB.
    /// </summary><remarks>
    /// Internally, this class manages a MemoryStream, and it contains a number of
    /// methods to make it easier to read and write data to the stream / message.
    /// </remarks>
    public class MessageStream
    {
        #region Public methods

        /// <summary>
        /// Constructor.
        /// </summary>
        public MessageStream()
        {
            m_Stream = new MemoryStream();
            m_Writer = new BinaryWriter(m_Stream);
            m_Reader = new BinaryReader(m_Stream);
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        public MessageStream(byte[] byteArray)
        {
            m_Stream = new MemoryStream(byteArray);
            m_Writer = new BinaryWriter(m_Stream);
            m_Reader = new BinaryReader(m_Stream);
        }

        /// <summary>
        /// Close method: cleans up the object.
        /// </summary>
        public void Close()
        {
            m_Writer.Close();
            m_Reader.Close();
        }

        /// <summary>
        /// Converts the stream to a byte-array.
        /// </summary>
        public byte[] toByteArray()
        {
            return m_Stream.ToArray();
        }

		/// <summary>
		/// Writes another MessageStream object to the stream.
		/// </summary>
		public void writeStream(MessageStream stream)
		{
			byte[] array = stream.toByteArray();
			m_Writer.Write(array.Length);
			m_Writer.Write(array);
		}

		/// <summary>
		/// Reads a MessageStream from the stream.
		/// </summary>
		public MessageStream readStream()
		{
			int iLength = m_Reader.ReadInt32();
			byte[] array = m_Reader.ReadBytes(iLength);
			return new MessageStream(array);
		}

		/// <summary>
		/// Writes a double to the stream.
		/// </summary>
		public void writeDouble(double value)
		{
			m_Writer.Write(value);
		}

		/// <summary>
		/// Reads a double from the stream.
		/// </summary>
		public double readDouble()
		{
			return m_Reader.ReadDouble();
		}

		/// <summary>
        /// Writes an int to the stream.
        /// </summary>
        public void writeInt(int value)
        {
            m_Writer.Write(value);
        }

        /// <summary>
        /// Reads and returns an int from the stream.
        /// </summary>
        public int readInt()
        {
            return m_Reader.ReadInt32();
        }

        /// <summary>
        /// Writes a string to the stream.
        /// </summary>
        public void writeString(string value)
        {
            m_Writer.Write(value);
        }

        /// <summary>
        /// Reads and returns a string from the stream.
        /// </summary>
        public string readString()
        {
            return m_Reader.ReadString();
        }

        /// <summary>
        /// Writes a float to the stream.
        /// </summary>
        public void writeBoolean(bool value)
        {
            m_Writer.Write(value);
        }

        /// <summary>
        /// Reads and returns a bool from the stream.
        /// </summary>
        public bool readBoolean()
        {
            return m_Reader.ReadBoolean();
        }

        /// <summary>
        /// Writes a float to the stream.
        /// </summary>
        public void writeFloat(float value)
        {
            m_Writer.Write(value);
        }

        /// <summary>
        /// Reads and returns a float from the stream.
        /// </summary>
        public float readFloat()
        {
            return m_Reader.ReadSingle();
        }

        /// <summary>
        /// Writes a GUID to the stream.
        /// </summary>
        public void writeGUID(Guid value)
        {
            m_Writer.Write(value.ToByteArray());
        }

        /// <summary>
        /// Reads and returns a GUID from the stream.
        /// </summary>
        public Guid readGUID()
        {
            byte[] data = m_Reader.ReadBytes(16);
            return new Guid(data);
        }

        /// <summary>
        /// Reads a RectangleF to the stream.
        /// </summary>
        public void writeRectangleF(RectangleF value)
        {
            m_Writer.Write(value.X);
            m_Writer.Write(value.Y);
            m_Writer.Write(value.Width);
            m_Writer.Write(value.Height);
        }

        /// <summary>
        /// Reads and returns a RectangleF from the stream.
        /// </summary>
        public RectangleF readRectangleF()
        {
            float x = m_Reader.ReadSingle();
            float y = m_Reader.ReadSingle();
            float width = m_Reader.ReadSingle();
            float height = m_Reader.ReadSingle();
            return new RectangleF(x, y, width, height);
        }

        /// <summary>
        /// Writes a Color to the stream.
        /// </summary>
        public void writeColor(Color value)
        {
            m_Writer.Write(value.ToArgb());
        }

        /// <summary>
        /// Reads and returns a Color from the stream.
        /// </summary>
        public Color readColor()
        {
            int argb = m_Reader.ReadInt32();
            return Color.FromArgb(argb);
        }

        /// <summary>
        /// Writes a PointF to the stream.
        /// </summary>
        public void writePointF(PointF value)
        {
            writeFloat(value.X);
            writeFloat(value.Y);
        }

        /// <summary>
        /// Reads and returns a PointF from the stream.
        /// </summary>
        public PointF readPointF()
        {
            float x = readFloat();
            float y = readFloat();
            return new PointF(x, y);
        }

        #endregion

        #region Private data

        private MemoryStream m_Stream = null;
        private BinaryWriter m_Writer = null;
        private BinaryReader m_Reader = null;


        #endregion

    }
}
